package com.cskaoyan.service.admin.popularize;

import com.cskaoyan.dao.polularize.MarketCouponDao;
import com.cskaoyan.dao.usercoupon.UserCouponDao;
import com.cskaoyan.exception.ParamsException;
import com.cskaoyan.model.admin.coupon.bo.CouponCreateInfoBo;
import com.cskaoyan.model.admin.coupon.bo.CouponListBo;
import com.cskaoyan.model.admin.coupon.bo.CouponUpdateBo;
import com.cskaoyan.model.admin.coupon.bo.CouponUserBo;
import com.cskaoyan.model.admin.coupon.vo.*;
import com.cskaoyan.model.admin.pojo.MarketCouponPojo;
import com.cskaoyan.utils.StringParseUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Transactional
public class CouPonServiceImpl implements CouPonService {

    @Autowired
    MarketCouponDao couponDao;

    @Autowired
    UserCouponDao userCouponDao;

    /**
     * @param bo :根据条件进行优惠券查询，分页，调用transferMarketCouponPojo将pojo和 Vo进行数据转换
     */
    @Override
    public CouponResponseVo getCouponList(CouponListBo bo) {
        // 检查更新库存
        checkAndUpdateCouponInfo(null);


        CouponResponseVo responseVo = new CouponResponseVo();


        PageHelper.startPage(bo.getPage(), bo.getLimit());
        final List<MarketCouponPojo> marketCouponInfo = couponDao.getMarketCouponInfo(bo);
        PageInfo<MarketCouponPojo> info = new PageInfo<>(marketCouponInfo);

        // 如果数量为-1返回0,

        responseVo.setLimit(bo.getLimit());
        responseVo.setPage(bo.getPage());
        responseVo.setTotal((int) info.getTotal());
        responseVo.setPages(info.getPages());
        responseVo.setList(transferMarketCouponPojo(marketCouponInfo));
        return responseVo;
    }

    /**
     * 每次查询之前用来更新数据库中的日期等优惠券信息
     */
    public void checkAndUpdateCouponInfo(Integer id) {

        List<Integer> updatePojoInfo = couponDao.getUpdatePojoIds(id);
        if (updatePojoInfo != null && updatePojoInfo.size() != 0) {
            couponDao.updateTimeInfo(updatePojoInfo);
        }
    }

    /**
     * @param id :根据ID查询到优惠券信息
     */
    @Override
    public CouponReadVo getCouponRead(Integer id) {
        MarketCouponPojo pojo = couponDao.getMarketCouponInfoById(id);
        return transferCouponReadVo(pojo);
    }

    /**
     * @param bo ：根据User_id 得到用户的信息【优惠券使用的详情]
     */
    @Override
    public CouponResponseVo getUserInfo(CouponUserBo bo) {
        PageHelper.startPage(bo.getPage(), bo.getLimit());
        List<CouponUserVo> list = userCouponDao.getCouponUserList(bo);
        PageInfo<CouponUserVo> info = new PageInfo<>(list);

        CouponResponseVo responseVo = new CouponResponseVo();
        responseVo.setPages(info.getPages());
        responseVo.setList(list);
        responseVo.setLimit(bo.getLimit());
        responseVo.setPage(bo.getPage());
        responseVo.setTotal((int) info.getTotal());
        return responseVo;
    }

    private CouponReadVo transferCouponReadVo(MarketCouponPojo pojo) {
        CouponReadVo vo = new CouponReadVo();
        vo.setId(pojo.getId());
        vo.setName(pojo.getName());
        vo.setDesc(pojo.getDesc());
        vo.setTag(pojo.getTag());

        vo.setTotal(String.valueOf(pojo.getTotal()));
        if (pojo.getTotal() == -1) {
            vo.setTotal("不限量");
        }

        vo.setCode(pojo.getCode());
        vo.setDiscount(pojo.getDiscount().doubleValue());
        vo.setMin(pojo.getMin().doubleValue());
        vo.setLimit(pojo.getLimit());
        vo.setType(pojo.getType());
        vo.setStatus(pojo.getStatus());
        vo.setGoodsType(pojo.getGoodsType());
        vo.setGoodsValue(StringParseUtils.getStringArr(pojo.getGoodsValue()));
        int i = pojo.getTimeType();
        vo.setTimeType(i);
        i = pojo.getDays();
        vo.setDays(i);
        SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        vo.setAddTime(formater.format(pojo.getAddTime()));
        vo.setUpdateTime(formater.format(pojo.getUpdateTime()));
        vo.setDeleted(pojo.getDeleted() == 1);
        return vo;
    }


    /***
     *
     * @param bo:根据条件进行插入数据
     * @return ：返回插入数据的全部字段
     */
    @Override
    public CouponAddDataVo addNewCoupon(CouponCreateInfoBo bo) {
        // 设置goodsValue根据goodsType决定
        if (bo.getGoodsType() != 0) {
            bo.setGoodsValueOfString(bo.getGoodsValue().toString());
        } else {
            bo.setGoodsValueOfString("[]");
        }
        // 设置code
        if (bo.getType() == 2) {
            bo.setCode(UUID.randomUUID().toString().substring(0, 8));
        }

        couponDao.addNewCouponInfo(bo);

        return transferCouponInfoBo(bo);
    }

    private CouponAddDataVo transferCouponInfoBo(CouponCreateInfoBo bo) {
        CouponAddDataVo vo = new CouponAddDataVo();
        vo.setId(bo.getId());
        vo.setName(bo.getName());
        vo.setDesc(bo.getDesc());
        vo.setTag(bo.getTag());
        vo.setTotal(bo.getTotal());
        vo.setDiscount(bo.getDiscount());
        vo.setMin(bo.getMin());
        vo.setLimit(bo.getLimit());
        vo.setType(bo.getType());
        vo.setStatus(bo.getStatus());
        vo.setGoodsType(bo.getGoodsType());
        vo.setGoodsValue(bo.getGoodsValue());
        vo.setTimeType(bo.getTimeType());
        vo.setDays(bo.getDays());
        vo.setStartTime(bo.getStartTime());
        vo.setEndTime(bo.getEndTime());

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:ss:mm");
        vo.setAddTime(format.format(new Date()));
        vo.setEndTime(bo.getEndTime());
        vo.setUpdateTime(format.format(new Date()));
        return vo;
    }

    /**
     * 更新的话，针对的是，
     * 1. 优惠券时间不可修改，【但是日期类型不能变】
     * 2. 增量，增多一些优惠券。
     * 3. 可使用的品类增加。
     * 4. 每人限领只能增加，不可降低。
     * 5. 商品的限制范围可以修改
     */
    @Override
    public CouponAddDataVo updateCouponInfo(CouponUpdateBo bo) throws ParamsException {

        // 如果更新的对象不存在
        MarketCouponPojo pojo = couponDao.getMarketCouponInfoById(bo.getId());
        if (pojo == null) {
            return null;
        }

        // 验证数据的正确性->如果以后增加需求在这里修改
        // 如果是删除不需要验证
        if (!bo.getDeleted()) {
            validateUpdateBo(pojo, bo);
            bo.setGoodsValueOfString(bo.getGoodsValue().toString());
        }

        // 设置一些参数
        bo.setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        couponDao.updateMarketCouponInfo(bo);

        return new CouponAddDataVo(bo);
    }

    /**
     * @param pojo:查询的所有的优惠券信息
     * @return :转换成对应的json需要的信息
     */
    private List<CouponListDataVo> transferMarketCouponPojo(List<MarketCouponPojo> pojo) {
        List<CouponListDataVo> list = new ArrayList<>();
        if (pojo == null) {
            return list;
        }

        for (MarketCouponPojo number : pojo) {
            CouponListDataVo node = new CouponListDataVo(number);
            list.add(node);
        }
        return list;
    }

    /**
     * 1. 时间类型不可修改，并且优惠券类型不可修改
     * 2. 优惠券类型不可修改
     *
     * 从什么维度决定一个优惠券是否唯一： 【时间类型，优惠券类型，每人限制领取数量，时间长短】
     */
    private void validateUpdateBo(MarketCouponPojo pojo, CouponUpdateBo bo) throws ParamsException {
        // 时间类型不可修改
        int timeType = pojo.getTimeType();
        if (timeType != bo.getTimeType()) {
            throw new ParamsException("日期类型不可修改");
        }

        // 优惠券类型不可变
        if (!pojo.getType().equals(bo.getType())) {
            throw new ParamsException("优惠券类型不可修改");
        }

        // 优惠券的每人限制领取数量不可减少
        if (pojo.getLimit() > Integer.parseInt(bo.getLimit())) {
            throw new ParamsException("没人限领取的优惠券数量不能减少");
        }

        // 绝对时间不可修改
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (timeType == 0) {
            int days = pojo.getDays();
            if (days != bo.getDays()) {
                throw new ParamsException("不可修改时间长短");
            }
        } else {
            String startTime = simpleDateFormat.format(pojo.getStartTime());
            String endTime = simpleDateFormat.format(pojo.getEndTime());
            if (!startTime.equals(bo.getStartTime()) || !endTime.equals(bo.getEndTime())) {
                throw new ParamsException("时间不可修改");
            }
        }
    }

}
